home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / dmake38c.zip / RUNARGV.C < prev    next >
C/C++ Source or Header  |  1992-01-23  |  7KB  |  300 lines

  1. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/unix/runargv.c,v 1.1 1992/01/24 03:28:50 dvadura Exp $
  2. -- SYNOPSIS -- invoke a sub process.
  3. -- 
  4. -- DESCRIPTION
  5. --     Use the standard methods of executing a sub process.
  6. --
  7. -- AUTHOR
  8. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  9. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  10. --
  11. -- COPYRIGHT
  12. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  13. -- 
  14. --      This program is free software; you can redistribute it and/or
  15. --      modify it under the terms of the GNU General Public License
  16. --      (version 1), as published by the Free Software Foundation, and
  17. --      found in the file 'LICENSE' included with this distribution.
  18. -- 
  19. --      This program is distributed in the hope that it will be useful,
  20. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  21. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22. --      GNU General Public License for more details.
  23. -- 
  24. --      You should have received a copy of the GNU General Public License
  25. --      along with this program;  if not, write to the Free Software
  26. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27. --
  28. -- LOG
  29. --     $Log: runargv.c,v $
  30.  * Revision 1.1  1992/01/24  03:28:50  dvadura
  31.  * dmake Version 3.8, Initial revision
  32.  *
  33. */
  34.  
  35. #include <signal.h>
  36. #include "extern.h"
  37. #include "sysintf.h"
  38.  
  39. typedef struct prp {
  40.    char *prp_cmd;
  41.    int   prp_group;
  42.    int   prp_ignore;
  43.    int   prp_last;
  44.    int     prp_shell;
  45.    struct prp *prp_next;
  46. } RCP, *RCPPTR;
  47.  
  48. typedef struct pr {
  49.    int        pr_valid;
  50.    int        pr_pid;
  51.    CELLPTR    pr_target;
  52.    int        pr_ignore;
  53.    int        pr_last;
  54.    RCPPTR      pr_recipe;
  55.    RCPPTR      pr_recipe_end;
  56.    char        *pr_dir;
  57. } PR;
  58.  
  59. static PR  *_procs    = NIL(PR);
  60. static int  _proc_cnt = 0;
  61. static int  _abort_flg= FALSE;
  62. static int  _use_i    = -1;
  63. static int  _do_upd   = 0;
  64.  
  65. static  void    _add_child ANSI((int, CELLPTR, int, int));
  66. static  void    _attach_cmd ANSI((char *, int, int, CELLPTR, int, int));
  67. static  void    _finished_child ANSI((int, int));
  68. static  int     _running ANSI((CELLPTR));
  69.  
  70. PUBLIC int
  71. runargv(target, ignore, group, last, shell, cmd)
  72. CELLPTR target;
  73. int     ignore;
  74. int    group;
  75. int    last;
  76. int     shell;
  77. char    *cmd;
  78. {
  79.    extern  int  errno;
  80.    extern  char *sys_errlist[];
  81.    int          pid;
  82.    char         **argv;
  83.  
  84.    if( _running(target) /*&& Max_proc != 1*/ ) {
  85.       /* The command will be executed when the previous recipe
  86.        * line completes. */
  87.       _attach_cmd( cmd, group, ignore, target, last, shell );
  88.       return(1);
  89.    }
  90.  
  91.    while( _proc_cnt == Max_proc )
  92.       if( Wait_for_child(FALSE, -1) == -1 )  Fatal( "Lost a child" );
  93.  
  94.    argv = Pack_argv( group, shell, cmd );
  95.  
  96.    switch( pid=fork() ){
  97.       int   wid;
  98.       int   status;
  99.  
  100.    case -1: /* fork failed */
  101.       Error("%s: %s", argv[0], sys_errlist[errno]);
  102.       Handle_result(-1, ignore, _abort_flg, target);
  103.       return(-1);
  104.  
  105.    case 0:  /* child */
  106.       execvp(argv[0], argv);
  107.       Continue = TRUE;   /* survive error message */
  108.       Error("%s: %s", argv[0], sys_errlist[errno]);
  109.       kill(getpid(), SIGTERM);
  110.       /*NOTREACHED*/
  111.  
  112.    default: /* parent */
  113.       _add_child(pid, target, ignore, last);
  114.    }
  115.  
  116.    return(1);
  117. }
  118.  
  119.  
  120. PUBLIC int
  121. Wait_for_child( abort_flg, pid )
  122. int abort_flg;
  123. int pid;
  124. {
  125.    int wid;
  126.    int status;
  127.    int waitchild;
  128.  
  129.    waitchild = (pid == -1)? FALSE : Wait_for_completion;
  130.  
  131.    do {
  132.       if( (wid = wait(&status)) == -1 ) return(-1);
  133.  
  134.       _abort_flg = abort_flg;
  135.       _finished_child(wid, status);
  136.       _abort_flg = FALSE;
  137.    }
  138.    while( waitchild && pid != wid );
  139.  
  140.    return(0);
  141. }
  142.  
  143.  
  144. PUBLIC void
  145. Clean_up_processes()
  146. {
  147.    register int i;
  148.  
  149.    if( _procs != NIL(PR) ) {
  150.       for( i=0; i<Max_proc; i++ )
  151.      if( _procs[i].pr_valid )
  152.         kill(_procs[i].pr_pid, SIGTERM);
  153.  
  154.       while( Wait_for_child(TRUE, -1) != -1 );
  155.    }
  156. }
  157.  
  158.  
  159. static void
  160. _add_child( pid, target, ignore, last )
  161. int    pid;
  162. CELLPTR target;
  163. int    ignore;
  164. int     last;
  165. {
  166.    register int i;
  167.    register PR *pp;
  168.  
  169.    if( _procs == NIL(PR) ) {
  170.       TALLOC( _procs, Max_proc, PR );
  171.    }
  172.  
  173.    if( (i = _use_i) == -1 )
  174.       for( i=0; i<Max_proc; i++ )
  175.      if( !_procs[i].pr_valid )
  176.         break;
  177.  
  178.    pp = _procs+i;
  179.  
  180.    pp->pr_valid  = 1;
  181.    pp->pr_pid    = pid;
  182.    pp->pr_target = target;
  183.    pp->pr_ignore = ignore;
  184.    pp->pr_last   = last;
  185.    pp->pr_dir    = _strdup(Get_current_dir());
  186.  
  187.    Current_target = NIL(CELL);
  188.  
  189.    _proc_cnt++;
  190.  
  191.    if( Wait_for_completion ) Wait_for_child( FALSE, pid );
  192. }
  193.  
  194.  
  195. static void
  196. _finished_child(pid, status)
  197. int    pid;
  198. int    status;
  199. {
  200.    register int i;
  201.    register PR *pp;
  202.    char     *dir;
  203.  
  204.    for( i=0; i<Max_proc; i++ )
  205.       if( _procs[i].pr_valid && _procs[i].pr_pid == pid )
  206.      break;
  207.  
  208.    /* Some children we didn't make esp true if using /bin/sh to execute a
  209.     * a pipe and feed the output as a makefile into dmake. */
  210.    if( i == Max_proc ) return;
  211.    _procs[i].pr_valid = 0;
  212.    _proc_cnt--;
  213.    dir = _strdup(Get_current_dir());
  214.    Set_dir( _procs[i].pr_dir );
  215.  
  216.    if( _procs[i].pr_recipe != NIL(RCP) && !_abort_flg ) {
  217.       RCPPTR rp = _procs[i].pr_recipe;
  218.  
  219.  
  220.       Current_target = _procs[i].pr_target;
  221.       Handle_result( status, _procs[i].pr_ignore, FALSE, _procs[i].pr_target );
  222.       Current_target = NIL(CELL);
  223.  
  224.       _procs[i].pr_recipe = rp->prp_next;
  225.  
  226.       _use_i = i;
  227.       runargv( _procs[i].pr_target, rp->prp_ignore, rp->prp_group,
  228.            rp->prp_last, rp->prp_shell, rp->prp_cmd );
  229.       _use_i = -1;
  230.  
  231.       FREE( rp->prp_cmd );
  232.       FREE( rp );
  233.  
  234.       if( _proc_cnt == Max_proc ) Wait_for_child( FALSE, -1 );
  235.    }
  236.    else {
  237.       Unlink_temp_files( _procs[i].pr_target );
  238.       Handle_result(status,_procs[i].pr_ignore,_abort_flg,_procs[i].pr_target);
  239.  
  240.       if( _procs[i].pr_last ) {
  241.      FREE(_procs[i].pr_dir );
  242.  
  243.      if( !Doing_bang ) Update_time_stamp( _procs[i].pr_target );
  244.       }
  245.    }
  246.  
  247.    Set_dir(dir);
  248.    FREE(dir);
  249. }
  250.  
  251.  
  252. static int
  253. _running( cp )
  254. CELLPTR cp;
  255. {
  256.    register int i;
  257.  
  258.    if( !_procs ) return(FALSE);
  259.  
  260.    for( i=0; i<Max_proc; i++ )
  261.       if( _procs[i].pr_valid &&
  262.       _procs[i].pr_target == cp  )
  263.      break;
  264.      
  265.    return( i != Max_proc );
  266. }
  267.  
  268.  
  269. static void
  270. _attach_cmd( cmd, group, ignore, cp, last, shell )
  271. char    *cmd;
  272. int    group;
  273. int     ignore;
  274. CELLPTR cp;
  275. int     last;
  276. int     shell;
  277. {
  278.    register int i;
  279.    RCPPTR rp;
  280.  
  281.    for( i=0; i<Max_proc; i++ )
  282.       if( _procs[i].pr_valid &&
  283.       _procs[i].pr_target == cp  )
  284.      break;
  285.  
  286.    TALLOC( rp, 1, RCP );
  287.    rp->prp_cmd   = _strdup(cmd);
  288.    rp->prp_group = group;
  289.    rp->prp_ignore= ignore;
  290.    rp->prp_last  = last;
  291.    rp->prp_shell = shell;
  292.  
  293.    if( _procs[i].pr_recipe == NIL(RCP) )
  294.       _procs[i].pr_recipe = _procs[i].pr_recipe_end = rp;
  295.    else {
  296.       _procs[i].pr_recipe_end->prp_next = rp;
  297.       _procs[i].pr_recipe_end = rp;
  298.    }
  299. }
  300.